package cc.rengu.igas.channel.cpcn.core.packswitch;

import cc.rengu.igas.channel.cpcn.common.constant.CpcnParamConstant;
import cc.rengu.igas.channel.cpcn.common.util.CpcnTransferUtil;
import cc.rengu.jradp.packetswitch.IncomingPackSwitchImpl;
import cc.rengu.jradp.packetswitch.OutgoingPackSwitchImpl;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.utility.util.StringUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import cc.rengu.utility.log.RgLog;
import cc.rengu.utility.log.RgLogger;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.ByteArrayInputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.RSAPublicKey;

/**
 * @author wukefan
 * @version 1.0.0
 * @date 2020/7/24 16:42
 */
public class CpcnNotifyPackSwitch implements IncomingPackSwitchImpl, OutgoingPackSwitchImpl {
    RgLogger rglog = RgLog.getLogger(this.getClass().getName());

    @Override
    public byte[] beforeInComPackSwitch(byte[] bytes) throws Exception {
        String openReqParam = new String(bytes, "UTF-8");
        rglog.debug("openReqParam = <{}>", openReqParam);
        JSONObject jsonObject = JSON.parseObject(openReqParam);
        String cpcnReqParam = jsonObject.getString("data").replace("<", "+");
        //message 使用base64解密
        byte[] message = Base64.decodeBase64(cpcnReqParam);
        /*XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        RSAPublicKey publicKey = null;
        //处理进入的请求
        String cpcnReqParam = new String(bytes,"UTF-8");
        rglog.debug("cpcnReqParam = <{}>",cpcnReqParam);
        //  cpcnReqParam    :message=*****&signature=???????
        String[] cpcnReqParamArr = cpcnReqParam.split("&signature=");
        Pattern p = Pattern.compile("\\s*|\t|\r|\n");
        Matcher m = p.matcher(cpcnReqParamArr[1]);
        String signData = m.replaceAll("");
        String [] messageArr = cpcnReqParamArr[0].split("message=");
        //message 使用base64解密
        byte[] message = Base64.decodeBase64(messageArr[1]);
        String instId = parseAndTransformMessage(message);
        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.INST_ID,instId);
        //验签
        if(StringUtil.isEmptyOrNull(signData)){
            //获取通道信息
            DstChannelCfgMapper dstChannelCfgMapper = new DstChannelCfgMapperImpl();
            DstChannelCfg dstChannelCfg = dstChannelCfgMapper.selectDstChannelCfgByPrimaryKey(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID),"CPCN","NET");
            if(null == dstChannelCfg){
                rglog.error("获取通道信息失败-->通道为<{}>","CPCN");
                throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(),RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
            }
            String secPlanId = dstChannelCfg.getSecPlanId();
            SecPlanInfoMapper secPlanInfoMapper = new SecPlanInfoMapperImpl();
            List<SecPlanInfo> secPlanInfoList = secPlanInfoMapper.selectSecPlanInfoBySecPlanId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID),secPlanId);
            if(null != secPlanInfoList && !secPlanInfoList.isEmpty()){
                xmlTreeUtil.setXmlTreeStringValue(CpcnTreeNodeConstant.SEC_PLAN_INFO_LIST, JSON.toJSONString(secPlanInfoList));
            }
            //获取验密证书
            Optional<SecPlanInfo> secPlanInfoOptional = secPlanInfoList.stream().filter(item -> item.getSecPlanType().equals(CpcnParamConstant.SIGN_CERT_TYPE_D)).findFirst();
            rglog.debug("获取证书索引<{}>",secPlanInfoOptional.get().getInstId()+secPlanInfoOptional.get().getSecPlanId()+secPlanInfoOptional.get().getSecPlanType());
            if(secPlanInfoOptional.isPresent()) {
                CertInfoMapper certInfoMapper = new CertInfoMapperImpl();
                CertInfo certInfo = certInfoMapper.selectCertInfoByPrimaryKey(secPlanInfoOptional.get().getInstId() + secPlanInfoOptional.get().getSecPlanId() + secPlanInfoOptional.get().getSecPlanType());
                if (null == certInfo) {
                    rglog.error("证书信息未配置,请先配置证书");
                    throw new BizException(RespCodeEnum.CERT_INFO_NOT_EXIST.getRespCode(), RespCodeEnum.CERT_INFO_NOT_EXIST.getRespDesc());
                }
                rglog.debug("证书存储类型<{}>", certInfo.getCertSaveType());
                //证书密钥串
                if ("0".equals(certInfo.getCertSaveType())) {
                    publicKey = RSAUtil.getPublicKeyFromBase64String(certInfo.getCertValue());
                } else if ("2".equals(certInfo.getCertSaveType())) {
                    List<String> aliasList = RSAUtil.getCertAliasFromPfxCertFile(certInfo.getCertSavePath(), certInfo.getCertPassword());
                    rglog.debug("证书别名<{}>", aliasList.iterator().next());
                    publicKey = RSAUtil.getPublicKeyFromPfxCertFile(certInfo.getCertSavePath(), aliasList.get(0), certInfo.getCertPassword());
                }
                rglog.debug("验证签名报文signature = <{}>", signData);
                if(verifySignature(message,StringUtil.hexStringToBinary(signData),publicKey,"SHA1WithRSA")){
                    rglog.debug("验签成功");
                    return message;
                }else{
                    rglog.error("验签失败");
                    return new byte[0];
                }
            }
        }*/
        return message;
    }


    @Override
    public int afterInComPackSwitch() throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        if (!StringUtil.isEmptyOrNull(xmlTreeUtil.getXmlTreeStringValue("txCode"))) {
            if ("1118".equals(xmlTreeUtil.getXmlTreeStringValue("txCode"))) {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, "T00CH500");
            }
            if ("1138".equals(xmlTreeUtil.getXmlTreeStringValue("txCode"))) {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, "T00CH501");
            }
        }
        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.SRC_SYS_ID, CpcnParamConstant.TUNL_ID_CPCN);
        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.BIZ_TYPE, CpcnParamConstant.DEFAULT_BIZ_TYPE);
        //机构信息转换
        String instId = null;
        if (!StringUtil.isEmptyOrNull(xmlTreeUtil.getXmlTreeStringValue("institutionId"))) {
            instId = CpcnTransferUtil.cpcnInstIdTransfer2CorpBank(xmlTreeUtil.getXmlTreeStringValue("institutionId"));
        }
        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.INST_ID, instId);
        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.CHANNEL_ID, "*");

        return 0;
    }

    @Override
    public int beforeOutgoPackSwitch() throws Exception {
        return 0;
    }

    @Override
    public byte[] afterOutgoPackSwitch(byte[] bytes) throws Exception {

        return bytes;
    }

    private boolean verifySignature(byte[] recvBuf, byte[] sign, RSAPublicKey publicKey, String algorithm) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
        Signature signature = Signature.getInstance(algorithm);
        signature.initVerify(publicKey);
        signature.update(recvBuf);
        return signature.verify(sign);
    }

    private String parseAndTransformMessage(byte[] message) throws DocumentException {
        String instId;
        SAXReader reader = new SAXReader();
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(message);
        Document document = reader.read(byteArrayInputStream);
        Element rootElement = document.getRootElement();
        rglog.debug("根节点名称 = <{}>", rootElement.getName());//根节点Request
        Element institutionIdElement = rootElement.element("Body").element("InstitutionID");
        String institutionId = institutionIdElement.getText();
        instId = CpcnTransferUtil.cpcnInstIdTransfer2CorpBank(institutionId);
        return instId;
    }
}
